﻿#region Copyright (c) 2008 plexBB Team

/*  Copyright (c) 2008 plexBB Team
 *  
 *  This file is free software: you may copy, redistribute and/or modify it  
 *  under the terms of the GNU General Public License as published by the  
 *  Free Software Foundation, either version 2 of the License, or (at your  
 *  option) any later version.  
 *  
 *  This file is distributed in the hope that it will be useful, but  
 *  WITHOUT ANY WARRANTY; without even the implied warranty of  
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 *  General Public License for more details.  
 *  
 *  You should have received a copy of the GNU General Public License  
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

#endregion

using System;
using System.Linq;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;
using PlexBB.Data;
using Module = PlexBB.Data.Module;

namespace PlexBB.Controls
{
    public abstract class ForumControl : UserControl
    {
        private const string ControlsPrefix = "PlexBB.Controls.";
        private const string ControlsLocation = "Styles/Prosilver/Templates";
        private const string AdminControlsPrefix = "PlexBB.Controls.Admin.";
        private const string AdminControlsLocation = "Resources/AdminStyle/Templates";

        private PlexBBContext _plexBBContext;

        public PlexBBContext PlexBBContext
        {
            get
            {
                // cache PlexBBContext to avoid numerous searches through HttpContext.Items collection
                return _plexBBContext ?? (_plexBBContext = PlexBBContext.Current);
            }
        }

        public Language Lang
        {
            get { return PlexBBContext.User.Lang; }
        }

        public User User
        {
            get { return PlexBBContext.User; }
        }

        public PlexBBData Data
        {
            get { return PlexBBContext.Data; }
        }

        public Module CurrentModule
        {
            get
            {
                return PlexBBContext.CurrentModule;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // check controls
            Type[] controlTypes = new[] { typeof(Control), typeof(IButtonControl), typeof(ITextControl) };
            string[] nullFields = (from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                   where controlTypes.FirstOrDefault(ct => ct.IsAssignableFrom(field.FieldType)) != null
                                         && field.GetValue(this) == null
                                   select field.Name).ToArray();
            if (nullFields.Length > 0)
            {
                throw new PlexBBException(string.Format("Mandatory control(s) {0} should exist in template {1}.",
                                                        string.Join(" ,", nullFields),
                                                        GetType().FullName));
            }
        }

        #region Create

        public static ForumControl Create(Type controlType)
        {
            //// load languages before loading control 
            //Language lang = PlexBBContext.Current.User.Lang;
            //foreach (RequiredLangFilesAttribute attribute in controlType.GetCustomAttributes(typeof(RequiredLangFilesAttribute), true))
            //{
            //    foreach (string langFile in attribute.LangFiles)
            //    {
            //        lang.Require(langFile);
            //    }
            //}

            // load ASCX file is control type is abstract
            // else just create control instance
            if (controlType.IsAbstract)
            {
                string prefix;
                string location;
                if (controlType.FullName.StartsWith(AdminControlsPrefix))
                {
                    prefix = AdminControlsPrefix;
                    location = AdminControlsLocation;
                }
                else
                {
                    prefix = ControlsPrefix;
                    location = ControlsLocation;
                }
                string controlPath = string.Format("{0}/{1}/{2}.ascx",
                                                   PlexBBContext.Current.Configuration.BaseDir.TrimEnd('/'),
                                                   location,
                                                   controlType.FullName.Substring(prefix.Length).Replace('.', '/'));
                return (ForumControl)PlexBBContext.Current.Page.LoadControl(controlPath);
            }
            else
            {
                return (ForumControl)Activator.CreateInstance(controlType);
            }
        }

        public static T Create<T>() where T : ForumControl
        {
            return (T)Create(typeof(T));
        }

        #endregion
    }
}